package service

import (
	"context"
	"encoding/json"
	"errors"
	"fx_swift_ifcgate_agent/api"
	"fx_swift_ifcgate_agent/internal/model"
	"fx_swift_ifcgate_agent/pkg/code"
	"fx_swift_ifcgate_agent/pkg/global"
	"fx_swift_ifcgate_agent/pkg/httputils"
	"fx_swift_ifcgate_agent/pkg/internalerrors"
	"fx_swift_ifcgate_agent/pkg/logger"
	"fx_swift_ifcgate_agent/pkg/utils"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/spf13/cast"
	"regexp"
)

func VerifyEmailFormat(email string) bool {
	pattern := `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*` //匹配电子邮箱
	reg := regexp.MustCompile(pattern)
	return reg.MatchString(email)
}

// 获取国家信息
func GetCountryInfo(ctx context.Context) ([]*api.GetCountryRes, error) {
	var (
		err         error
		countryList []*model.FxCountry
	)
	if err = global.GFDB.Model("fx_country").Scan(&countryList); err != nil {
		logger.SugarLogger.Error(err)
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	result := make([]*api.GetCountryRes, 0)
	for _, value := range countryList {
		result = append(result, &api.GetCountryRes{
			Id: value.ID,
			NameInfo: api.NameInfo{
				ChineseName: value.ChineseName,
				EnglishName: value.EnglishName,
			},
			CountryCode:    value.CountryCode,
			IsoCountryCode: value.IsoCountryCode,
			Status:         value.Status,
		})
	}
	return result, err
}

// 通过代理商账户查询商户号
func GetAccountToMerchantNo(account string) (string, error) {
	var (
		err            error
		companyUserObj *model.IfcgateCompanyUser
	)
	if err = global.GFDB.Ctx(context.Background()).Model("ifcgate_company_user").
		Where("agent_account=?", account).Scan(&companyUserObj); err != nil {
		logger.SugarLogger.Error(err)
		return "", nil
	}
	if companyUserObj == nil {
		return "", nil
	}
	return companyUserObj.MerchantNo, err
}

// 通过merchantNo获取ottPayToken
func GetMerchantToToken(ctx context.Context, merchantNo string) (string, error) {
	var (
		err         error
		redisResult *gvar.Var
	)
	redisResult, err = g.Redis().Get(ctx, merchantNo)
	if err != nil || redisResult.Val() == nil {
		logger.SugarLogger.Error(err)
		return "", nil
	}
	return redisResult.String(), err
}

// 获取币种对应的编码和中文
func GetCurrencyInfo(ctx context.Context) ([]*api.GetCurrencyInfoRes, error) {
	var (
		err          error
		currencyList []*model.IfcgateCurrency
	)
	if err = global.GFDB.Schema("fx").Model("ifcgate_currency").Where("1=1").Scan(&currencyList); err != nil {
		logger.SugarLogger.Error(err)
		return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	result := make([]*api.GetCurrencyInfoRes, 0)
	for _, value := range currencyList {
		result = append(result, &api.GetCurrencyInfoRes{
			CurrencyCode: value.CurrencyCode,
			CurrencyName: value.CurrencyName,
			Image:        value.Image,
		})
	}
	return result, err
}

func PostTp3004(req *api.Tp3004Req, merchantToken string) (*api.Tp3004Res, error) {
	var (
		err    error
		body   []byte
		resStr []byte
	)
	body, err = json.Marshal(&req)
	if err != nil {
		logger.SugarLogger.Errorf("json转换:%w", err)
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	resStr, err = OperatorParamToPost("tp3004", merchantToken, body)
	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	ottPayResult := &api.Tp3004Res{}
	err = json.Unmarshal(resStr, &ottPayResult)
	if err != nil {
		logger.SugarLogger.Errorf("json转换:%w", err)
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	if ottPayResult.Head.RespDesc == "请求成功" && ottPayResult.Head.RespCode == "S00000" {
		return ottPayResult, err
	}
	return nil, err
}

func PostTp1002(req *api.Tp1002Req, merchantToken string) (*api.Tp1002Res, error) {
	var (
		err    error
		body   []byte
		resStr []byte
	)
	body, err = json.Marshal(&req)
	if err != nil {
		logger.SugarLogger.Errorf("json转换:%w", err)
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	resStr, err = OperatorParamToPost("tp1002", merchantToken, body)
	if err != nil {
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	ottPayResult := &api.Tp1002Res{}
	err = json.Unmarshal(resStr, &ottPayResult)
	if err != nil {
		logger.SugarLogger.Errorf("json转换:%w", err)
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	if ottPayResult.Head.RespDesc == "请求成功" && ottPayResult.Head.RespCode == "S00000" {
		return ottPayResult, err
	}
	return nil, err
}

// 请求OTTPay参数封装
func OperatorParamToPost(tradeCode, accessToken string, body []byte) ([]byte, error) {
	var (
		err  error
		resp string
		url  string
	)
	url = global.ViperObj.GetString("ottpay.baseUrl") + tradeCode
	//组装请求头参数
	reqMap := httputils.GetRequestParam(tradeCode, accessToken)
	//组装请求体参数
	reqBody := make(map[string]interface{})
	err = json.Unmarshal(body, &reqBody)
	if err != nil {
		return nil, err
	}
	reqMap["body"] = reqBody

	//转换成byte
	jsonData, err := json.Marshal(reqMap)
	//请求参数加密
	request := utils.Encrtpt(string(jsonData), global.ViperObj.GetString("ottpay.merChantNo"))
	reqJson, _ := json.Marshal(request)
	resp = httputils.DoPost(url, reqJson)
	if resp == "" {
		logger.SugarLogger.Errorf("响应报文为空:%s", resp)
		return nil, errors.New("响应报文为空")
	}
	var resBean = &api.Bean{}
	err = json.Unmarshal([]byte(resp), &resBean)
	if err != nil {
		logger.SugarLogger.Errorf("json 读取报错:%w", err)
		return nil, err
	}
	//解密并且封装实体
	resStr, err := utils.Decrypt(resBean)
	if err != nil {
		logger.SugarLogger.Errorf("响应报文解密报错:%w", err)
		return nil, err
	}
	headObj := &api.JsonStr{}
	err = json.Unmarshal(resStr, &headObj)
	//校验返回结果是否有异常，有则返回异常信息
	if headObj.Head.RespDesc != "请求成功" && headObj.Head.RespDesc != "S00000" {
		return nil, errors.New(headObj.Head.RespDesc)
	}
	return resStr, err
}

// 所有账户的币种转为USD
func AccountsCurrencyToUSD(merchantToken string) (map[string]float64, error) {
	var (
		err          error
		tp3004Result *api.Tp3004Res
	)
	isNoUsdMap := make(map[string]float64)
	isUsdMap := make(map[string]float64)
	finalMap := make(map[string]float64)
	tp3004Result, err = PostTp3004(&api.Tp3004Req{}, merchantToken)
	if len(tp3004Result.Tp3004InfoList.Tp3004Info) > 0 {
		for _, valueObj := range tp3004Result.Tp3004InfoList.Tp3004Info {
			if valueObj.Balance != "0.00" && valueObj.Currency != "USD" {
				if _, ok := isNoUsdMap[valueObj.Currency]; !ok {
					isNoUsdMap[valueObj.Currency] = cast.ToFloat64(valueObj.Balance)
				} else {
					tAmount := isNoUsdMap[valueObj.Currency]
					isNoUsdMap[valueObj.Currency] = cast.ToFloat64(valueObj.Balance) + tAmount
				}
			} else {
				if _, ok := isUsdMap[valueObj.Currency]; !ok {
					isUsdMap[valueObj.Currency] = cast.ToFloat64(valueObj.Balance)
				} else {
					tAmount := isUsdMap[valueObj.Currency]
					isUsdMap[valueObj.Currency] = cast.ToFloat64(valueObj.Balance) + tAmount
				}
			}
		}
		for key, value := range isNoUsdMap {
			finalMap[key] = value
		}
		for key, value := range isUsdMap {
			finalMap[key] = value
		}
	}
	return finalMap, err
}

func GetPurposeList(ctx context.Context) ([]*api.PurposeRes, error) {
	var (
		err        error
		purposeObj []*model.IFCPurpose
	)

	if err = global.GFDB.Model("ifcgate_purpose_base").Scan(&purposeObj); err != nil {
		logger.SugarLogger.Error(err)
		return []*api.PurposeRes{}, internalerrors.New(code.ErrUnknown, "数据查询异常")
	}
	if purposeObj == nil {
		logger.SugarLogger.Error(err)
		return []*api.PurposeRes{}, nil
	}

	purposeList := make([]*api.PurposeRes, 0)
	for _, value := range purposeObj {
		purposeList = append(purposeList, &api.PurposeRes{
			Code: value.Code,
			Desc: api.DescList{
				DescZh: value.DescZh,
				DescEn: value.DescEn,
			},
		})
	}

	return purposeList, nil
}
